home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / comm / bbs / s342q16.lha / routmail.c < prev    next >
C/C++ Source or Header  |  1996-08-29  |  52KB  |  2,102 lines

  1. /*
  2. *                RoutMail.c
  3. *
  4. * Reads in a net map for C86Net-style mail routing.
  5. */
  6. /*
  7. * NB: With the advent of domain mail routing most of this code has become
  8. * irrelevant.  Don't get worked up about trying to figure out this code
  9. * because this entire utility is probably used very very little by anyone.
  10. */
  11. /*
  12. *                History
  13. *
  14. * 89Nov30  HAW Route locking (1.10)
  15. * 89Nov29  HAW Route optimization (1.9).
  16. * 89Jul26  HAW Miscellaneous fixes (1.7).
  17. * 89Jun13  HAW Make ReDoRouted() return TRUE at end (1.4).
  18. * 89Jun07  HAW Support for encryption of mail files. (1.3).
  19. * 89May03  HAW Integrity check on dead systems still on list (1.2).
  20. * 89Apr04  HAW Fix for the virtual room capability (1.1).
  21. * 89Jan--  HAW Initial creation finished, V1.
  22. */
  23. /*
  24. *                Contents
  25. *
  26. *    AddNewNode()        adds a new node to the node list.
  27. *    BackToDirect()        return a route to direct connect
  28. *    CheckAccessible()    Runs through map for routing.
  29. *    FindHub()        Find a hub in the netmap.
  30. *    FindPeon()        Find a peon in the netmap.
  31. *    GetLine()        Gets a line from file.
  32. *    HubHub()        Hubs talking to hubs.
  33. *    InitSystem()        open up data base files.
  34. *    main()            Main manager of program.
  35. *    MakeMap()        Reads in the PEONs section of map.
  36. *    ParseId()        Splits line into node ID and Name.
  37. *    ProcessDead()        Process "dead" section of the netmap.
  38. *    ReadArguments()        Read command line arguments.
  39. *    ReadHubs()        Reads in the HUBS section of map.
  40. *    SetHub()        Route path to a hub node.
  41. *    SetNode()        Sets up routing path.
  42. *    SetPeon()        Route path to a peon node.
  43. *    SetUpHub()        Set up a hub for processing.
  44. *    ShowArguments()        Inform user of valid arguments.
  45. *    WeAreHub()        Handles us being a hub node.
  46. *    WeArePeon()        Handles us being a peon node.
  47. */
  48. #include "ctdl.h"
  49. #include "citamap.h"
  50. #define DEFAULT_NET    (1l << 14)
  51. #define MAP_NAME    "ROUTEMAP"
  52. /* Names of options for mapper. */
  53. #define ADD_NODES    "+add"
  54. #define KILL_NODES    "+kill"
  55. #define DISCARD_MAIL    "+discard"
  56. #define MANUAL_MODE    "+manual"
  57. #define DOMAIN_MODE    "+domains"
  58. /* Warning messages.    */
  59. #define UNKNOWN_HUB         "WARNING: We are attached to a hub named %s (%s) of which we know nothing!\n"
  60. #define SURPRISE_ROUTE   "SURPRISE!  We were routing Mail to a node we did not know: %s (%s)\n."
  61. #define DISCARD_UNKNOWN  "We'll discard this Mail to the unknown node.\n"
  62. #define DISCARD_KNOWN    "Discarding mail being routed to %s via %s.\n"
  63. #define REROUTING           "Rerouting mail for %s via %s.\n"
  64. #define ERROR_LOCAL_MAIL "Couldn't open direct mail file for %s!\n"
  65. #define MAIL_IN_TRANSIT     "ERROR: Map says to delete %s, but it has mail in transit from:\n"
  66. #define HAS_ROUTED         "ERROR: %s is to be reached indirectly, but it has mail in transit!\n"
  67. /* Explanations    */
  68. #define ADD_EXPLAIN         "\t%s -- cause unknown nodes to be added to your node list.\n"
  69. #define KILL_EXPLAIN     "\t%s -- cause nodes in DEAD section to be deleted from your node list.\n"
  70. #define NEW_NODE           "%s @%s added: non-local / %s / net 15.\n"
  71. #define DISCARD             "\t%s -- discard routed mail which can't be rerouted.\n\t\t(Use with caution.)\n"
  72. #define MANUAL_EXPLAIN   "\t%s -- use the node editor.\n"
  73. #define DOMAIN_EXPLAIN   "\t%s -- add domain handlers (found in ctdldmhd.sys) to CtdlNet.Sys.\n"
  74. /* Exit error codes    */
  75. #define DEAD_IS_HUB         "Node %s is present both as a hub and a dead node.\n"
  76. #define DEAD_IS_PEON       "Node %s is present both as a peon and a dead node.\n"
  77. #define NO_ERRORS          0
  78. #define NO_FILE_NAMED   1
  79. #define MAP_ERROR          2
  80. #define NO_SYS_TABLE    3
  81. #define LF_ERROR          4
  82. #define SYSTEM_CRASH    10
  83. char inNet = NORMAL_NET;
  84. /*
  85. Thoughts on topology map.
  86. o Could organize it as a set of hubs.  Each hub could have: hubs to which
  87. it connects, peons to which it connects.  Or do we need the explicit
  88. recognition?   Can we handle just a "who does he connect with directly"
  89. organization?  We don't* want to maintain differing netmaps for each
  90. area of the net.  It seems we might need a path resolution algorithm
  91. in the map reader.  Hell, we have code space since this'll be a utility
  92. program ... hmmm.  Let's experiment with the idea.
  93. o After some thought ... what if we make it a necessity that a system
  94. running the route utility be on that map?  This may help us resolve
  95. the situation.  If we can identify our own node on the list (above), then
  96. we can also recognize our situation, as either a "hub" of some sort, or
  97. a normal "peon".
  98. - peons simply route everything non-local to the hub (or hubs) in their
  99. area.  Ah, a rub: what if there's more than one hub, such as Images/
  100. Test System, or UCC/KAOS?  Hmmmmmm.
  101. o After writing some of the code and thinking about path resolution,
  102. multiple backbones in one area, etc ... I think we need the map itself
  103. to be more intelligent.  Let's divide it into two areas: HUBS and PEONS.
  104. The HUB area would describe how the HUBS are configured -- who talks to
  105. who.  The PEONS area is a listing what peons are connected to what HUBs.
  106. o I also now think we need to model the topography in the resultant data
  107. instantiation: we should be able to easily tell (from reading the netmap)
  108. who talks to who.  More structures ...
  109. */
  110. /*
  111. * Map Data structure:
  112. *
  113. *  Two areas.  The second is a HUBS area, listing all hubs and who talks to
  114. *  who.  The first is a PEONS list -- what peons are connected to what HUB.
  115. *
  116. *  Each area is a series of records.  Each record is separated from the next by
  117. *  a blank line.  First item is the name of the system which connects directly
  118. *  with the system(s) which follow it.
  119. *
  120. *  Systems are identified by <nodeId>:<nodeName>.
  121. *    US 612 470 9635 : C-86 Test System
  122. *
  123. *  Perhaps it would make sense to require the start of the Node ID be in
  124. *  the first column, otherwise it's a comment.
  125. *
  126. *  Later thought: A third section named "DOWN" might be an appropriate way
  127. *  to get permanently down systems off the netlist.
  128. */
  129. /*
  130. * Routing optimization:
  131. *   We need to do route optimization because the maps now may contain
  132. * more than one path to a node, and sometimes the router will choose
  133. * the "worse" path.  Therefore, for each distinct node in the map we
  134. * will have to maintain a "hop count" to that node.  When we find a
  135. * new path to any node, we first check our current hop count for this
  136. * node and, if it's better (less) then we reset the path, otherwise
  137. * not.
  138. */
  139. int FindHopCount(char *Id);
  140. NetBuffer nBuf1, nBuf2;
  141. FILE *wfd;
  142. char  AddNodes    = FALSE;
  143. char  KillNodes   = FALSE;
  144. char  DiscardMail = FALSE;
  145. char  Manual      = FALSE;
  146. char  DoDomains   = FALSE;
  147. extern FILE *upfd;
  148. HUB  *Systems;
  149. label OurId;
  150. int   CurHubNet, callSlot, Pass;
  151. SListBase FwdAliasii =
  152.   {
  153.   NULL, ChkNtoStr, NULL, FreeNtoStr, EatNMapStr
  154.  
  155.   };
  156. SListBase DeadNodes  =
  157.   {
  158.   NULL, NULL, NULL, free, NULL
  159.  
  160.   };
  161. SListBase AreaList   =
  162.   {
  163.   NULL, CheckArea, NULL, NULL, NULL
  164.  
  165.   };
  166. extern SListBase Serves;
  167. void *FindDomainH(), *EatDomainH();
  168. static SListBase DomainHandlers =
  169.   {
  170.   NULL, FindDomainH, NULL, free, EatDomainH
  171.  
  172.   };
  173. typedef struct
  174.   {
  175.   char *domain;
  176.   char *name;
  177.   char *nodeId;
  178.  
  179.   }
  180. DomainHandler;
  181. char *rates[] =
  182.   {
  183.   "300", "1200", "2400", "4800", "9600", "14400", "19200", "38400", "57600"
  184.  
  185.   };
  186. /* this is here to satisfy a library */
  187. char onConsole = FALSE, remoteSysop = FALSE;
  188. FILE *netLog = NULL;
  189. extern CONFIG    cfg;
  190. extern NetBuffer netBuf, netTemp;
  191. extern int     thisNet;
  192. extern FILE     *netfl;
  193. extern MessageBuffer   msgBuf;
  194. extern NetTable  *netTab;
  195. SListBase MailForward =
  196.   {
  197.   NULL, NULL, NULL, NULL, NULL
  198.  
  199.   };
  200. /*
  201. * AddNewNode()
  202. *
  203. * This function adds a new node to the internal node list we maintain.
  204. */
  205. void AddNewNode(Name, Id, baud)
  206. label Name, Id;
  207. int baud;
  208.   {
  209.   int rover, gen;
  210.   /*
  211.   * This function adds a new node to the node list.
  212.   * 1. Scavenge for unused node.  If none found, then we make new one.
  213.   * 2. Zero it.
  214.   * 3. Copy in Name & Id.
  215.   * 4. Assume node is non-local & mark it so.  Announce to world.
  216.   * 5. Assume node is 1200 baud, announce to world.
  217.   * 6. Set node to member net 15 only.  Announce to world.
  218.   * 7. Save node.
  219.   */
  220.   rover = GetNewSlot(&netBuf);
  221.   gen = netBuf.nbGen;
  222.   /*    zero the node -- watch out for pointer problems!  */
  223.   killNetBuf(&netBuf);
  224.   zero_struct(netBuf);
  225.   initNetBuf(&netBuf);
  226.   netBuf.nbGen = gen;
  227.   strCpy(netBuf.netName, Name);
  228.   strCpy(netBuf.netId, Id);
  229.   netBuf.nbflags.in_use   = TRUE;    /* yes, we live!   */
  230.   netBuf.nbflags.local    = FALSE;
  231.   netBuf.nbflags.RouteFor = TRUE;
  232.   netBuf.nbflags.RouteTo  = TRUE;
  233.   netBuf.MemberNets        = DEFAULT_NET;
  234.   if (baud != -1)
  235.   netBuf.baudCode    = baud;
  236.   else
  237.   netBuf.baudCode    = 1;
  238.   netBuf.nbRoute    = -1;    /* No route.    */
  239.   printf(NEW_NODE, Name, Id, rates[netBuf.baudCode]);
  240.   putNet(rover, &netBuf);
  241.   InitVNode(rover);
  242.  
  243.   }
  244. /*
  245. * GetNewSlot(n)
  246. *
  247. * This function gets a new slot for adding a new node.
  248. */
  249. int GetNewSlot(n)
  250. NetBuffer *n;
  251.   {
  252.   int rover;
  253.   /* rover will be set right at the end of this. */
  254.   for (rover = 0; rover < cfg.netSize; rover++)
  255.   if (!netTab[rover].ntflags.in_use)
  256.     {
  257.     getNet(rover, n);
  258.     break;
  259.  
  260.     }
  261.   if (rover == cfg.netSize)
  262.     {
  263.     cfg.netSize++;
  264.     n->nbGen = 0;
  265.     if (cfg.netSize == 1)
  266.     netTab = GetDynamic(sizeof *netTab);
  267.     else
  268.     netTab = realloc(netTab, sizeof (*netTab) * cfg.netSize);
  269.     netTab[rover].netTRooms = GetDynamic(SR_BULK);
  270.  
  271.     }
  272.   else n->nbGen = (n->nbGen + 1) % NET_GEN;
  273.   return rover;
  274.  
  275.   }
  276. /*
  277. * BackToDirect()
  278. *
  279. * We are no longer routing to this node, but going direct.
  280. */
  281. void BackToDirect(system, n)
  282. int system;
  283. NetBuffer *n;
  284.   {
  285.   label    Id, Name, temp, TarId;
  286.   SYS_FILE fn, fn2;
  287.   int i = 0, LastRoute;
  288.   if (n->nbRoute == -1) return ;
  289.   normId(n->netId, TarId);
  290.   getNet(n->nbRoute, &nBuf1);
  291.   LastRoute = FindRouteName(system, fn);
  292.   do
  293.     {
  294.     sPrintf(temp, "R%d.%d", n->nbRoute, i);
  295.     makeSysName(fn, temp, &cfg.netArea);
  296.     if (IdRouteFile(fn, Id, Name))
  297.       {
  298.       if (strCmpU(Id, TarId) == SAMESTRING)
  299.         {
  300.         sprintf(temp, "R%d.%d", system, LastRoute++);
  301.         makeSysName(fn2, temp, &cfg.netArea);
  302.         rename(fn, fn2);
  303.         CoverRouteHole(n->nbRoute, i);
  304.  
  305.         }
  306.       else i++;
  307.  
  308.       }
  309.     else break;
  310.  
  311.     }
  312.   while (TRUE);
  313.   if (i == 0)
  314.   nBuf1.nbflags.HasRouted = FALSE;
  315.   nBuf1.nbHiRouteInd = i;
  316.   putNet(n->nbRoute, &nBuf1);
  317.   if (LastRoute != 0) n->nbflags.HasRouted = TRUE;
  318.   n->nbHiRouteInd = LastRoute - 1;
  319.  
  320.   }
  321. /*
  322. * CheckAccessible()
  323. *
  324. * This function helps run through the map, making routes.
  325. */
  326. void CheckAccessible(HUB *HomeHub, HUB *CurHub, PEONS *Kr, int HopCount)
  327.   {
  328.   PEONS *Krover;
  329.   LINKS *LinkRover;
  330.   if (CurHub->Checked < Pass || IsLowerHopCount(CurHub->Id, HopCount))
  331.     {
  332.     /* So we don't circle the wagons on and on and on ... */
  333.     CurHub->Checked = Pass;
  334.     /* Set CurHub to be accessed via HomeHub. */
  335.     SetHub(CurHub, HomeHub, HopCount);
  336.     /*
  337.     * For all nodes directly handled by this hub, set us up to
  338.     * go through HomeHub to get to that node iff that node is
  339.     * non-local.
  340.     */
  341.     for (Krover = CurHub->list; Krover != NULL; Krover = Krover->next)
  342.     if (Krover != Kr)
  343.     SetPeon(Krover, HomeHub, HopCount);
  344.     /*
  345.     * Now we need to go through every node on the list which we may
  346.     * access and set it to be accessible via the hub node we are
  347.     * currently using.  We do this by traversing the list of HUBs which
  348.     * the current HUB may access, which is contained in the Hub field of
  349.     * each hub in the list.  In order to avoid looping, we must check
  350.     * each Hub's flag before processing it, and set it if not set yet.
  351.     *
  352.     * Fortunately, we can do this recursively, I think.
  353.     */
  354.     for (LinkRover = CurHub->Hubs; LinkRover != NULL;
  355.     LinkRover = LinkRover->next)
  356.     CheckAccessible(HomeHub, LinkRover->Hub, Kr, HopCount + 1);
  357.  
  358.     }
  359.  
  360.   }
  361. /*
  362. * CoverRouteHole()
  363. *
  364. * This function creates file names for routing files.  It must create them
  365. * in an ascending numerical order of the form "r<num>.<num>", where the
  366. * first number is the node index its associated with (routing mail to) and
  367. * the second is the sequence number.
  368. */
  369. void CoverRouteHole(system, start)
  370. int system, start;
  371.   {
  372.   int i;
  373.   label temp;
  374.   SYS_FILE fn, fn2;
  375.   for (i = start + 1; ; i++)
  376.     {
  377.     sPrintf(temp, "R%d.%d", system, i);
  378.     makeSysName(fn, temp, &cfg.netArea);
  379.     if (access(fn, 0) == -1) break;
  380.     sPrintf(temp, "R%d.%d", system, i - 1);
  381.     makeSysName(fn2, temp, &cfg.netArea);
  382.     rename(fn, fn2);
  383.  
  384.     }
  385.  
  386.   }
  387. /*
  388. * crashout()
  389. *
  390. * This is the general crash routine.  Needed by getNet, etc.
  391. */
  392. void crashout(str)
  393. char *str;
  394.   {
  395.   printf(str);
  396.   writeSysTab();
  397.   exit(SYSTEM_CRASH);
  398.  
  399.   }
  400. /*
  401. * FindHub()
  402. *
  403. * This function will check for the existence of a node in the hub list.
  404. */
  405. HUB *FindHub(base, id)
  406. HUB *base;
  407. label id;
  408.   {
  409.   HUB *rover;
  410.   for (rover = base; rover != NULL; rover = rover->next)
  411.   if (strCmp(id, rover->Id) == SAMESTRING)
  412.   return rover;
  413.   return NULL;
  414.  
  415.   }
  416. /*
  417. * FindGlobalPeon()
  418. *
  419. * This function finds a peon anywhere in the map.
  420. */
  421. PEONS *FindGlobalPeon(base, id)
  422. HUB *base;
  423. label id;
  424.   {
  425.   HUB *rover;
  426.   PEONS *toReturn = NULL;
  427.   for (rover = base; rover != NULL; rover = rover->next)
  428.   if ((toReturn = FindPeon(rover->list, id)) != NULL)
  429.   break;
  430.   return toReturn;
  431.  
  432.   }
  433. /*
  434. * FindPeon()
  435. *
  436. * This finds if a given id is in a list of peons.
  437. */
  438. PEONS *FindPeon(base, id)
  439. PEONS *base;
  440. label id;
  441.   {
  442.   PEONS *rover;
  443.   for (rover = base; rover != NULL; rover = rover->next)
  444.   if (strCmpU(id, rover->Id) == SAMESTRING)
  445.   return rover;
  446.   return NULL;
  447.  
  448.   }
  449. /*
  450. * GetLine()
  451. *
  452. * This function gets a line from file, strips some shit out.
  453. */
  454. char *GetLine(line, s, fd)
  455. char *line;
  456. int  s;
  457. FILE *fd;
  458.   {
  459.   int i;
  460.   do
  461.     {
  462.     if (fgets(line, s, fd) == NULL)
  463.     return NULL;
  464.     /* Strip trailing blanks. */
  465.     for (i = strLen(line) - 1; i >= 0; i--)
  466.       {
  467.       if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ')
  468.       break;  /* non-whitespace, so break     */
  469.       line[i] = 0;
  470.  
  471.       }
  472.  
  473.     }
  474.   while (line[0] == ' ' || line[0] == '\t');
  475.   return line;
  476.  
  477.   }
  478. /*
  479. * HubHub()
  480. *
  481. * This handles the direct hub to hub and then the trace.  This is here to
  482. * circumvent the "Checked" variable, just in case there's a loop in the net
  483. * topology which would have us sending route mail on a long loop when we
  484. * actually directly connect to the hub in question.  Note this is a poor
  485. * man's attempt at net optimization, and consideration might be worth giving
  486. * to doing true optimization in the future.
  487. * 89Nov30 -- ok, with the hopcount stuff we're trying to optimize
  488. */
  489. void HubHub(Us, Hub)
  490. HUB *Us, *Hub;
  491.   {
  492.   char Connected;
  493.   if ((CurHubNet = searchNet(Hub->Id, &netTemp)) == ERROR)
  494.     {
  495.     if (!AddNodes)
  496.       {
  497.       Connected = FALSE;
  498.       printf(UNKNOWN_HUB, Hub->Name, Hub->Id);
  499.       /* return ; */
  500.  
  501.       }
  502.     else
  503.       {
  504.       Connected = TRUE;
  505.       AddNewNode(Hub->Name, Hub->Id, Hub->baud);
  506.       CurHubNet = thisNet;
  507.       getNet(CurHubNet, &netTemp);
  508.  
  509.       }
  510.  
  511.     }
  512.   else Connected = TRUE;
  513.   if (Connected)
  514.     {
  515.     if (!DirectRoute(&netTemp))
  516.     BackToDirect(CurHubNet, &netTemp);
  517.     netTemp.nbRoute = -1;   /* Direct route. */
  518.     putNet(CurHubNet, &netTemp);
  519.  
  520.     }
  521.   Hub->Checked--;    /* Deactivate flag -- some more poor    */
  522.   /* man optimization.                    */
  523.   SetHopCount(Hub->Id, 0, NULL);
  524.   CheckAccessible(Hub, Hub, NULL, 1);
  525.  
  526.   }
  527. /*
  528. * InitSystem()
  529. *
  530. * This function will open up appropriate data base files, and initialize
  531. * buffers.
  532. */
  533. void InitSystem()
  534.   {
  535.   SYS_FILE name;
  536.   extern FILE *logfl;
  537.   extern logBuffer logTmp, logBuf;
  538.   /* Open database files. */
  539.   makeSysName(name, "ctdlnet.sys", &cfg.netArea);
  540.   openFile(name, &netfl);
  541.   makeSysName(name, "ctdllog.sys", &cfg.logArea);
  542.   openFile(name, &logfl);
  543.   initLogBuf(&logTmp);
  544.   initLogBuf(&logBuf);
  545.   InitMsgBase();
  546.   /* Now initialize data buffers. */
  547.   initNetBuf(&netBuf);
  548.   initNetBuf(&netTemp);
  549.   initNetBuf(&nBuf1);
  550.   initNetBuf(&nBuf2);
  551.   makeSysName(name, "ctdlalsi.sys", &cfg.roomArea);
  552.   MakeList(&FwdAliasii, name, upfd);
  553.   VirtInit();
  554.  
  555.   }
  556. /*
  557. * KillMapNodes()
  558. *
  559. * This function kills a node if possible, in accordance with map directions.
  560. */
  561. void KillMapNodes(Id)
  562. label Id;
  563.   {
  564.   label    temp;
  565.   SYS_FILE fn;
  566.   if (FindHub(Systems, Id) != NULL)
  567.     {
  568.     printf(DEAD_IS_HUB, Id);
  569.     exit(MAP_ERROR);
  570.  
  571.     }
  572.   if (FindGlobalPeon(Systems, Id) != NULL)
  573.     {
  574.     printf(DEAD_IS_PEON, Id);
  575.     exit(MAP_ERROR);
  576.  
  577.     }
  578.   if (searchNet(Id, &netBuf) != ERROR)
  579.     {
  580.     if (netBuf.nbflags.HasRouted)
  581.       {
  582.       sprintf(temp, "R%d.0", thisNet);
  583.       makeSysName(fn, temp, &cfg.netArea);
  584.       if (access(fn, 0) == 0)
  585.         {
  586.         printf(MAIL_IN_TRANSIT, netBuf.netName);
  587.         PrintRouteIds();
  588.         return;
  589.  
  590.         }
  591.  
  592.       }
  593.     printf("Deleting '%s'.\n", netBuf.netName);
  594.     KillAuxFiles();    /* kill support files */
  595.     netBuf.nbflags.in_use = FALSE;
  596.     putNet(thisNet, &netBuf);
  597.  
  598.     }
  599.  
  600.   }
  601. HUB  *Us;
  602. /*
  603. * main()
  604. *
  605. * The main manager for routemap eater.
  606. */
  607. main(argc, argv)
  608. int  argc;
  609. char **argv;
  610.   {
  611.   char filename[100];
  612.   printf(R_TITLE);
  613.   if (argc < 2)
  614.     {
  615.     ShowArguments();
  616.     exit(NO_FILE_NAMED);
  617.  
  618.     }
  619.   if (!ReadArguments(argc, argv, filename))
  620.     {
  621.     printf("ERROR: No discernible file name found.\n\n");
  622.     ShowArguments();
  623.     exit(NO_FILE_NAMED);
  624.  
  625.     }
  626.   if (!readSysTab(FALSE, TRUE))
  627.     {
  628.     printf("Couldn't read system table.\n");
  629.     exit(NO_SYS_TABLE);
  630.  
  631.     }
  632.   if (access(LOCKFILE, 0) != ERROR)
  633.     {
  634.     printf("Please do not run RoutMail using Outside Commands.\n");
  635.     writeSysTab();
  636.     exit(LF_ERROR);
  637.  
  638.     }
  639.   InitSystem();    /* Open needed data files    */
  640.   if (Manual)
  641.   DoEdit();
  642.   else
  643.     {
  644.     if ((Systems = MakeMap(filename)) == NULL)
  645.       {
  646.       writeSysTab();
  647.       exit(MAP_ERROR);
  648.  
  649.       }
  650.     if (KillNodes)    RunList(&DeadNodes, KillMapNodes);
  651.     /* normalize our id */
  652.     normId(cfg.codeBuf + cfg.nodeId, OurId);
  653.     SetHopCount(OurId, -1, NULL);
  654.     /* Find ourselves */
  655.     Pass = 1;
  656.     if ((Us = FindHub(Systems, OurId)) != NULL)
  657.     WeAreHub(Us, Systems);
  658.     else
  659.     WeArePeon(Systems);
  660.     /* now do it again! */
  661.     Pass = 2;
  662.     if ((Us = FindHub(Systems, OurId)) != NULL)
  663.     WeAreHub(Us, Systems);
  664.     else
  665.     WeArePeon(Systems);
  666.     if (DoDomains) HandleDomains();
  667.  
  668.     }
  669.   writeSysTab();
  670.   exit(NO_ERRORS);
  671.   return NO_ERRORS;
  672.  
  673.   }
  674. /*
  675. * MakeMap()
  676. *
  677. * This reads in the PEONs section of the map.
  678. */
  679. HUB *MakeMap(fn)
  680. char *fn;
  681.   {
  682.   SYS_FILE temp;
  683.   FILE  *fd;
  684.   char  line[100], found = FALSE;
  685.   HUB   base, *HubRover, *HubCur;
  686.   PEONS kbase, *KnownRover, *KnownCur;
  687.   extern char *READ_TEXT;
  688.   if ((fd = fopen(fn, READ_TEXT)) == NULL)
  689.     {
  690.     printf("Couldn't open '%s'.\n", fn);
  691.     return NULL;
  692.  
  693.     }
  694.   while (!found)
  695.     {
  696.     if (GetLine(line, 100, fd) == NULL) break;
  697.     if (strCmpU(line, "PEONS") == SAMESTRING) found = TRUE;
  698.  
  699.     }
  700.   if (!found)
  701.     {
  702.     printf("ERROR: Never found PEONS heading.\n");
  703.     return NULL;
  704.  
  705.     }
  706.   printf("\nReading PEON lists.\n");
  707.   base.next = NULL;
  708.   HubCur = &base;
  709.   do
  710.     {
  711.     /* get data */
  712.     do
  713.     if (GetLine(line, 100, fd) == NULL)
  714.       {
  715.       printf("ERROR: No HUBS section encountered.\n");
  716.       return NULL;    /* where's the HUB section? */
  717.  
  718.       }
  719.     while (strLen(line) == 0);    /* skip leading blank lines */
  720.     if (strCmpU(line, "HUBS") == SAMESTRING)
  721.     break;        /* end of PEONS section     */
  722.     /* now construct a hub node */
  723.     HubRover = (HUB *) GetDynamic(sizeof base);
  724.     HubRover->Hubs = NULL;    /* init */
  725.     HubRover->Checked = 0;    /* init */
  726.     if (!Parse(HubRover->Id, HubRover->Name, &HubRover->baud, line))
  727.     return NULL;
  728.     AddNewHop(HubRover->Id);
  729.     if (FindHub(base.next, HubRover->Id) != NULL)
  730.       {
  731.       printf("Hub multiply defined! (%s)\n", HubRover->Id);
  732.       return NULL;
  733.  
  734.       }
  735.     HubCur->next = HubRover;
  736.     HubRover->next = NULL;
  737.     HubCur = HubRover;
  738.     /* now construct the list of "known" nodes */
  739.     kbase.next = NULL;
  740.     KnownCur = &kbase;
  741.     do
  742.       {
  743.       if (GetLine(line, 100, fd) == NULL)
  744.         {
  745.         printf("ERROR: No HUBS section encountered.\n");
  746.         return NULL;
  747.  
  748.         }
  749.       if (strLen(line) == 1 || strLen(line) == 0)
  750.       break;    /* end of record indicator    */
  751.       KnownRover = (PEONS *) GetDynamic(sizeof kbase);
  752.       if (!Parse(KnownRover->Id, KnownRover->Name, &KnownRover->baud, line))
  753.       return NULL;
  754.       AddNewHop(KnownRover->Id);
  755.       if (FindPeon(kbase.next, KnownRover->Id) != NULL)
  756.         {
  757.         printf("PEON %s multiply defined!\n", KnownRover->Id);
  758.         return NULL;
  759.  
  760.         }
  761.       KnownCur->next = KnownRover;
  762.       KnownCur = KnownRover;
  763.       KnownCur->next = NULL;
  764.  
  765.       }
  766.     while (TRUE);
  767.     HubRover->list = kbase.next;
  768.  
  769.     }
  770.   while (TRUE);
  771.   if (!ReadHubs(base.next, fd))
  772.   return NULL;
  773.   fclose(fd);
  774.   if (DoDomains)
  775.     {
  776.     makeSysName(temp, "ctdldmhd.sys", &cfg.netArea);
  777.     if (!MakeList(&DomainHandlers, temp, NULL))
  778.     printf("Warning: %s was not found for processing!\n", temp);
  779.     makeSysName(temp, "ctdldmhd.lcl", &cfg.netArea);
  780.     MakeList(&DomainHandlers, temp, NULL);
  781.  
  782.     }
  783.   return base.next;
  784.  
  785.   }
  786. /*
  787. * Parse()
  788. *
  789. * This function takes a line and splits it into node ID and Name.
  790. */
  791. char Parse(Id, Name, baud, line)
  792. char *line;
  793. label Id, Name;
  794. int *baud;
  795.   {
  796.   char *s, *t, *u;
  797.   /* Guaranteed on entry that line is non-comment or separator */
  798.   if ((s = strchr(line, ':')) == NULL)
  799.   return FALSE;    /* No colon?  ERROR! */
  800.   *s = 0;
  801.   if (strLen(line) >= NAMESIZE)    /* Error checking!    */
  802.   return FALSE;
  803.   normId(line, Id);
  804.   s++;
  805.   /* Skip over leading white space after the colon, before the name. */
  806.   while (*s && (*s == ' ' || *s == '\t')) s++;
  807.   if ((u = t = strchr(s, '@')) != NULL)
  808.     {
  809.     *t = 0;
  810.     for (u--; *u == ' ' || *u == '\t'; u--)
  811.     ;
  812.     u++;
  813.     *u = 0;
  814.  
  815.     }
  816.   if (strLen(s) >= NAMESIZE)    /* Error checking!    */
  817.   return FALSE;
  818.   strCpy(Name, s);
  819.   if (t != NULL)
  820.     {
  821.     for (t++; *t == ' ' || *t == '\t'; t++)
  822.     ;
  823.     if (strLen(t))
  824.       {
  825.       switch (atoi(t))
  826.         {
  827.         case 300: *baud = 0; break;
  828.         case 1200: *baud = 1; break;
  829.         case 2400: *baud = 2; break;
  830.         case 4800: *baud = 3; break;
  831.         case 9600: *baud = 4; break;
  832.         case 14400: *baud = 5; break;
  833.         case 19200: *baud = 6; break;
  834.         default: printf("Unknown baud rate %s\n", t);
  835.  
  836.         }
  837.  
  838.       }
  839.     else *baud = -1;
  840.  
  841.     }
  842.   else *baud = -1;
  843.   return TRUE;
  844.  
  845.   }
  846. /*
  847. * ParseCh()
  848. *
  849. * This function parses a Change to a system's number or name.
  850. */
  851. char ParseCh(OldId, NewId, Name, baud, line)
  852. char *line;
  853. label NewId, OldId, Name;
  854. int *baud;
  855.   {
  856.   char *s, *t, *u;
  857.   /* Guaranteed on entry that line is non-comment or separator */
  858.   if ((s = strchr(line, ':')) == NULL)
  859.   return FALSE;    /* No colon?  ERROR! */
  860.   *s = 0;
  861.   if (strLen(line) >= NAMESIZE)    /* Error checking!    */
  862.   return FALSE;
  863.   normId(line, OldId);
  864.   s++;
  865.   if ((t = strchr(s, ':')) == NULL)
  866.   return FALSE;    /* No colon?  ERROR! */
  867.   *t = 0;
  868.   if (strLen(s) >= NAMESIZE)    /* Error checking!    */
  869.   return FALSE;
  870.   normId(s, NewId);
  871.   t++;
  872.   s = t;
  873.   /* Skip over leading white space after the colon, before the name. */
  874.   while (*s && (*s == ' ' || *s == '\t')) s++;
  875.   if ((u = t = strchr(s, '@')) != NULL)
  876.     {
  877.     *t = 0;
  878.     for (u--; *u == ' ' || *u == '\t'; u--)
  879.     ;
  880.     u++;
  881.     *u = 0;
  882.  
  883.     }
  884.   if (strLen(s) >= NAMESIZE)    /* Error checking!    */
  885.   return FALSE;
  886.   strCpy(Name, s);
  887.   if (t != NULL)
  888.     {
  889.     for (t++; *t == ' ' || *t == '\t'; t++)
  890.     ;
  891.     if (strLen(t))
  892.       {
  893.       switch (atoi(t))
  894.         {
  895.         case 300: *baud = 0; break;
  896.         case 1200: *baud = 1; break;
  897.         case 2400: *baud = 2; break;
  898.         case 4800: *baud = 3; break;
  899.         case 9600: *baud = 4; break;
  900.         case 14400: *baud = 5; break;
  901.         case 19200: *baud = 6; break;
  902.         default: printf("Unknown baud rate %s\n", t);
  903.  
  904.         }
  905.  
  906.       }
  907.     else *baud = -1;
  908.  
  909.     }
  910.   else *baud = -1;
  911.   return TRUE;
  912.  
  913.   }
  914. /*
  915. * ProcessDead()
  916. *
  917. * This function should process the "dead" section of the netmap.
  918. */
  919. char ProcessDead(fd)
  920. FILE *fd;
  921.   {
  922.   char line[100];
  923.   label Name, Id, *temp;
  924.   int baud;
  925.   /* Are we allowed to kill dead nodes? */
  926.   if (!KillNodes)
  927.   return TRUE;
  928.   while (GetLine(line, 100, fd) != NULL)
  929.     {
  930.     if (strCmpU(line, "COMMENTARY") == SAMESTRING) break;
  931.     if (!Parse(Id, Name, &baud, line))
  932.     continue;    /* return to top of loop */
  933.     temp = GetDynamic(sizeof *temp);
  934.     strCpy(*temp, Id);
  935.     AddData(&DeadNodes, temp, NULL, FALSE);
  936.  
  937.     }
  938.   return TRUE;
  939.  
  940.   }
  941. /*
  942. * ReadArguments()
  943. *
  944. * This function reads command line arguments.
  945. */
  946. char ReadArguments(argc, argv, filename)
  947. int  argc;
  948. char **argv, *filename;
  949.   {
  950.   int rover;
  951.   for (rover = 1; rover < argc; rover++)
  952.     {
  953.     if (strCmpU(argv[rover], ADD_NODES) == SAMESTRING)
  954.     AddNodes = TRUE;
  955.     else if (strCmpU(argv[rover], KILL_NODES) == SAMESTRING)
  956.     KillNodes = TRUE;
  957.     else if (strCmpU(argv[rover], DISCARD_MAIL) == SAMESTRING)
  958.     DiscardMail = TRUE;
  959.     else if (strCmpU(argv[rover], DOMAIN_MODE) == SAMESTRING)
  960.     DoDomains = TRUE;
  961.     else if (strCmpU(argv[rover], MANUAL_MODE) == SAMESTRING)
  962.       {
  963.       Manual = TRUE;
  964.       return TRUE;
  965.  
  966.       }
  967.     else
  968.       {
  969.       strCpy(filename, argv[rover]);
  970.       return TRUE;
  971.  
  972.       }
  973.  
  974.     }
  975.   return FALSE;
  976.  
  977.   }
  978. /*
  979. * ReadHubs()
  980. *
  981. * This function reads in the HUBS section.
  982. */
  983. char ReadHubs(base, fd)
  984. HUB *base;
  985. FILE *fd;
  986.   {
  987.   char line[100];
  988.   label Name, Id;
  989.   LINKS lbase, *lr, *clr;
  990.   HUB   *Targ;
  991.   int   baud;
  992.   printf("\nReading HUBS.\n");
  993.   /*
  994.   * "HUBS" already encountered.
  995.   */
  996.   do
  997.     {
  998.     do
  999.     if (GetLine(line, 100, fd) == NULL)
  1000.     return TRUE;
  1001.     while (strLen(line) == 0);    /* skip leading blank lines */
  1002.     if (strCmpU(line, "DEAD") == SAMESTRING)
  1003.     break;        /* end of HUBS section     */
  1004.     if (strCmpU(line, "CHANGES") == SAMESTRING)
  1005.     break;        /* end of HUBS section     */
  1006.     if (strCmpU(line, "COMMENTARY") == SAMESTRING)
  1007.     break;
  1008.     if (!Parse(Id, Name, &baud, line))
  1009.     return FALSE;
  1010.     printf("HUB %s\n", Name);
  1011.     AddNewHop(Id);
  1012.     if ((Targ = FindHub(base, Id)) == NULL)
  1013.       {
  1014.       printf("'%s' not found from PEONs section.\n", Name);
  1015.       return FALSE;
  1016.  
  1017.       }
  1018.     if (Targ->Hubs != NULL)
  1019.       {
  1020.       printf("'%s' already defined in HUBS section.\n",
  1021.       Name);
  1022.       return FALSE;
  1023.  
  1024.       }
  1025.     clr = &lbase;
  1026.     clr->next = NULL;
  1027.     do
  1028.       {
  1029.       if (GetLine(line, 100, fd) == NULL)
  1030.       break;
  1031.       if (strLen(line) == 1 || strLen(line) == 0)
  1032.       break;    /* end of record indicator    */
  1033.       lr = (LINKS *) GetDynamic(sizeof lbase);
  1034.       if (!Parse(Id, Name, &baud, line))
  1035.         {
  1036.         return FALSE;
  1037.  
  1038.         }
  1039.       AddNewHop(Id);
  1040.       if ((lr->Hub = (void *) FindHub(base, Id)) == NULL)
  1041.         {
  1042.         lr->Hub = (HUB *) GetDynamic(sizeof *Targ);
  1043.         strCpy(lr->Hub->Name, Name);
  1044.         strCpy(lr->Hub->Id, Id);
  1045.         lr->Hub->baud = baud;
  1046.         if (searchNet(Id, &netBuf) == ERROR)
  1047.         if (AddNodes) AddNewNode(Name, Id, baud);
  1048.  
  1049.         }
  1050.       clr->next = lr;
  1051.       clr = lr;
  1052.  
  1053.       }
  1054.     while (TRUE);
  1055.     clr->next = NULL;
  1056.     Targ->Hubs = lbase.next;    /* don't check for NULL */
  1057.  
  1058.     }
  1059.   while (TRUE);
  1060.   if (strCmpU(line, "DEAD") == SAMESTRING)
  1061.   return ProcessDead(fd);
  1062.   else if (strCmpU(line, "CHANGES") == SAMESTRING)
  1063.   return ProcChanges(fd);
  1064.   return TRUE;
  1065.  
  1066.   }
  1067. /*
  1068. * ProcChanges()
  1069. *
  1070. * This function will process the CHANGES section.
  1071. */
  1072. char ProcChanges(fd)
  1073. FILE *fd;
  1074.   {
  1075.   char line[100];
  1076.   label Name, OldId, NewId;
  1077.   LINKS lbase, *lr, *clr;
  1078.   HUB   *Targ;
  1079.   int   baud;
  1080.   printf("\nReading CHANGES.\n");
  1081.   /*
  1082.   * "CHANGES" already encountered.
  1083.   */
  1084.   do
  1085.     {
  1086.     do
  1087.     if (GetLine(line, 100, fd) == NULL)
  1088.     return TRUE;
  1089.     while (strLen(line) == 0);    /* skip leading blank lines */
  1090.     if (strCmpU(line, "DEAD") == SAMESTRING)
  1091.     break;    /* end of CHANGES section    */
  1092.     if (strCmpU(line, "COMMENTARY") == SAMESTRING)
  1093.     break;
  1094.     if (!ParseCh(OldId, NewId, Name, &baud, line))
  1095.     return FALSE;
  1096.     if (searchNet(NewId, &netBuf) == ERROR)
  1097.     if (searchNet(OldId, &netBuf) == ERROR)
  1098.     continue;
  1099.     ReDoAuxFiles(NewId);    /* changes aux files as needed */
  1100.     strCpy(netBuf.netId, NewId);
  1101.     strCpy(netBuf.netName, Name);
  1102.     /* if baud specified */
  1103.     if (baud != -1)
  1104.     netBuf.baudCode = baud;
  1105.     putNet(thisNet, &netBuf);
  1106.  
  1107.     }
  1108.   while (TRUE);
  1109.   if (strCmpU(line, "DEAD") == SAMESTRING)
  1110.   return ProcessDead(fd);
  1111.   return TRUE;
  1112.  
  1113.   }
  1114. /*
  1115. * SetHub()
  1116. *
  1117. * This sets up a route path to a hub node.
  1118. */
  1119. void SetHub(HUB *CurHub, HUB *HomeHub, int HopCount)
  1120.   {
  1121.   SetNode(CurHub->Name, CurHub->Id,CurHub->baud, HomeHub->Id, HopCount, TRUE);
  1122.  
  1123.   }
  1124. /*
  1125. * SetPeon()
  1126. *
  1127. * This sets up a route path to a peon node.
  1128. */
  1129. void SetPeon(PEONS *Peon, HUB *HomeHub, int HopCount)
  1130.   {
  1131.   SetNode(Peon->Name, Peon->Id, Peon->baud, HomeHub->Id, HopCount, TRUE);
  1132.  
  1133.   }
  1134. /*
  1135. * SetNode()
  1136. *
  1137. * This function sets up routing path.
  1138. */
  1139. void SetNode(TargetName, TargetId, TargetBaud, RouteId, HopCount, CheckHops)
  1140. label TargetName, TargetId, RouteId;
  1141. int   TargetBaud, HopCount;
  1142. char CheckHops;
  1143.   {
  1144.   char New = FALSE, NotAlive = FALSE;
  1145.   /*
  1146.   * We check to make sure target and router aren't the same.  If they
  1147.   * are, then there's no reason to do anything further here.
  1148.   */
  1149.   if (strCmp(TargetId, RouteId) == SAMESTRING)
  1150.   return;
  1151.   /*
  1152.   * Check to see if already present in net list.
  1153.   */
  1154.   if (searchNet(TargetId, &netBuf) == ERROR)
  1155.     {
  1156.     if (!AddNodes)
  1157.       {
  1158.       NotAlive = TRUE;
  1159.  
  1160.       }
  1161.     else
  1162.       {
  1163.       AddNewNode(TargetName, TargetId, TargetBaud);
  1164.       New = TRUE;
  1165.  
  1166.       }
  1167.  
  1168.     }
  1169.   /*
  1170.   * If system is local, then we don't try to setup a route.  Let the
  1171.   * sysop do it manually, instead.
  1172.   */
  1173.   if (!NotAlive && netBuf.nbflags.local)
  1174.     {
  1175.     SetHopCount(TargetId, 0, NULL);    /* direct connect -- 0 hops */
  1176.     return;
  1177.  
  1178.     }
  1179.   /*
  1180.   * If the RouteLock flag is set, then don't do this.
  1181.   */
  1182.   if (!NotAlive && netBuf.nbflags.RouteLock)
  1183.   return;
  1184.   if (!NotAlive && (DirectRoute(&netBuf) ||
  1185.   (!DirectRoute(&netBuf) && netBuf.nbRoute != CurHubNet)))
  1186.     {
  1187.     if (!CheckHops || IsLowerHopCount(TargetId, HopCount))
  1188.       {
  1189.       if (!New)
  1190.       printf("Changing route for %s to use %s (%d).\n",netBuf.netName,
  1191.       netTemp.netName, HopCount);
  1192.       if (ReRoute(CurHubNet))
  1193.         {
  1194.         netBuf.nbRoute    = CurHubNet;
  1195.         netBuf.nbRouteGen = netTemp.nbGen;
  1196.         putNet(thisNet, &netBuf);
  1197.         SetHopCount(TargetId, HopCount, RouteId);
  1198.  
  1199.         }
  1200.       else if (Pass == 2)
  1201.       printf(HAS_ROUTED, netBuf.netName);
  1202.  
  1203.       }
  1204.  
  1205.     }
  1206.   else SetHopCount(TargetId, HopCount, RouteId);
  1207.  
  1208.   }
  1209. /*
  1210. * SetUpHub()
  1211. *
  1212. * This function will set up a hub for processing by/for a peon.
  1213. */
  1214. char SetUpHub(Hr)
  1215. HUB *Hr;
  1216.   {
  1217.   if ((CurHubNet = searchNet(Hr->Id, &netTemp)) == ERROR)
  1218.     {
  1219.     if (!AddNodes)
  1220.       {
  1221.       printf(UNKNOWN_HUB, Hr->Name, Hr->Id);
  1222.       CurHubNet = -1;
  1223.       if (!DoDomains) return FALSE;
  1224.  
  1225.       }
  1226.     else
  1227.       {
  1228.       AddNewNode(Hr->Name, Hr->Id, Hr->baud);
  1229.       getNet(thisNet, &netTemp);
  1230.       CurHubNet = thisNet;
  1231.  
  1232.       }
  1233.  
  1234.     }
  1235.   if (CurHubNet != -1 && !DirectRoute(&netTemp))
  1236.     {
  1237.     printf("Changing %s to be a direct link.\n", netTemp.netName);
  1238.     BackToDirect(CurHubNet, &netTemp);
  1239.  
  1240.     }
  1241.   SetHopCount(Hr->Id, 0, NULL);    /* direct connect, now */
  1242.   netTemp.nbRoute = -1;   /* Force direct comm with this hub.    */
  1243.   return TRUE;
  1244.  
  1245.   }
  1246. /*
  1247. * ShowArguments()
  1248. *
  1249. * Inform user of valid arguments.
  1250. */
  1251. void ShowArguments()
  1252.   {
  1253.   printf("Usage: %s [options] <map name>\n\n", MAP_NAME);
  1254.   printf("Options:\n");
  1255.   printf(ADD_EXPLAIN, ADD_NODES);
  1256.   printf(KILL_EXPLAIN, KILL_NODES);
  1257.   printf(DISCARD, DISCARD_MAIL);
  1258.   printf(MANUAL_EXPLAIN, MANUAL_MODE);
  1259.   printf(DOMAIN_EXPLAIN, DOMAIN_MODE);
  1260.  
  1261.   }
  1262. /*
  1263. * WeAreHub()
  1264. *
  1265. * This function handles processing if we are a hub system.
  1266. */
  1267. void WeAreHub(Us, Systems)
  1268. HUB *Us, *Systems;
  1269.   {
  1270.   LINKS *LinkRunner;
  1271.   PEONS *peons;
  1272.   /*
  1273.   * As a hub, we need to know which hub will take us to other peons
  1274.   * and other hubs.  We'll do this by traversing all the hubs we
  1275.   * can talk to, and all of their peons.  This should seem quite
  1276.   * a bit like we did for WeArePeon(), I hope.
  1277.   *
  1278.   * However, at the moment we do not attempt to process our own list of
  1279.   * peons.  We assume these are all set up correctly.  This could, of
  1280.   * course, be changed in the future.
  1281.   */
  1282.   Us->Checked = Pass;    /* So we don't process ourselves.    */
  1283.   for (LinkRunner = Us->Hubs; LinkRunner != NULL;
  1284.   LinkRunner = LinkRunner->next)
  1285.   HubHub(Us, LinkRunner->Hub);
  1286.   for (peons = Us->list; peons != NULL; peons = peons->next)
  1287.     {
  1288.     if (searchNet(peons->Id, &netBuf) == ERROR)
  1289.     AddNewNode(peons->Name, peons->Id, peons->baud);
  1290.     if (!DirectRoute(&netBuf) && !netBuf.nbflags.RouteLock)
  1291.       {
  1292.       BackToDirect(thisNet, &netBuf);
  1293.       netBuf.nbRoute = -1;
  1294.       printf("Changing %s to be a direct link.\n", netBuf.netName);
  1295.  
  1296.       }
  1297.     SetHopCount(peons->Id, 0, NULL);
  1298.     putNet(thisNet, &netBuf);
  1299.  
  1300.     }
  1301.  
  1302.   }
  1303. /*
  1304. * WeArePeon()
  1305. *
  1306. * This function handles us being a peon node.
  1307. */
  1308. void WeArePeon(Systems)
  1309. HUB *Systems;
  1310.   {
  1311.   HUB *Hr;
  1312.   PEONS *Kr, *Kkr;
  1313.   char found = FALSE;
  1314.   /*
  1315.   * If we are in this function, we have verified we are not a hub
  1316.   * for anyone.  This implies, due to the structure of the netmap, that
  1317.   * we may exist in more than one hub's peon listing.  Therefore, we must
  1318.   * traverse all hubs' peon listings, searching for ourselves.  For each
  1319.   * one we find ourselves in, we using that hub's listing of other hubs
  1320.   * it directly talks to in order to assign the route for those nodes
  1321.   * accessible via those hubs to the current hub (confusing? yeah).
  1322.   *
  1323.   * Since those hubs directly accessible via the current hub may talk to
  1324.   * yet more hubs, thus allowing us access to yet more nodes, both hub and
  1325.   * peon, CheckAccessible() has been recursively designed ("goddamned son
  1326.   * of a...") to follow those hubs, assigning the current hub (the one we
  1327.   * started with) as the routing node.
  1328.   */
  1329.   for (Hr = Systems; Hr != NULL; Hr = Hr->next)
  1330.     {
  1331.     for (Kr = Hr->list; Kr != NULL; Kr = Kr->next)
  1332.       {
  1333.       if (strCmp(Kr->Id, OurId) == SAMESTRING)
  1334.         {
  1335.         found = TRUE;
  1336.         if (SetUpHub(Hr))
  1337.           {
  1338.           CheckAccessible(Hr, Hr, Kr, 1);
  1339.           if (CurHubNet != -1) putNet(CurHubNet, &netTemp);
  1340.  
  1341.           }
  1342.  
  1343.         }
  1344.  
  1345.       }
  1346.  
  1347.     }
  1348.   if (!found)
  1349.     {
  1350.     printf("ERROR: We do not seem to be anywhere on the map.\n");
  1351.  
  1352.     }
  1353.  
  1354.   }
  1355. /*
  1356. * ReRoute()
  1357. *
  1358. * This function handles rerouting mail for nodes with changing routes.  If
  1359. * you're going to read this code, you must be familiar with how routed mail
  1360. * is being stored.
  1361. */
  1362. char ReRoute(target)
  1363. int target;
  1364.   {
  1365.   /*
  1366.   * Here are the steps we need to take, and why, remembering that we
  1367.   * are seeing this node before its routing code has been changed:
  1368.   *
  1369.   * 1. If this system directly connected before, check to see if there
  1370.   *    is any outstanding mail.  If so, convert the local outstanding
  1371.   *    to route format and attach to the new route node's queue.
  1372.   *
  1373.   * 2. If this system directly connected before, check to see if there
  1374.   *    is any mail being routed via this node to other nodes.  If so,
  1375.   *    scan this mail to discover targets.  For each target, discover
  1376.   *    if we may reroute through another node.  If not, then we either
  1377.   *    abort the change for this node or discard the mail, depending
  1378.   *    on the command line arguments of the user.  If we abort, return
  1379.   *    FALSE.
  1380.   *
  1381.   * 3. If this system was not directly connected before, find the
  1382.   *    routed mail, using the old routing code in netBuf, and extract
  1383.   *    the routed Mail for rerouting.  We must also do a lot of renaming
  1384.   *    here.
  1385.   */
  1386.   if (DirectRoute(&netBuf))
  1387.     {
  1388.     /* first check for mail routing through this node. */
  1389.     if (!ChangeRouting(target)) return FALSE;
  1390.     /* now check local mail    */
  1391.     RouteLocalMail(target);
  1392.  
  1393.     }
  1394.   else
  1395.     {
  1396.     DoReRoute(target);
  1397.  
  1398.     }
  1399.   return TRUE;
  1400.  
  1401.   }
  1402. /*
  1403. * ReDoRouted()
  1404. *
  1405. * Dunno.
  1406. */
  1407. char ReDoRouted(target)
  1408. int target;
  1409.   {
  1410.   SYS_FILE fn, fn2;
  1411.   label temp1, temp, Name, Id, TarId;
  1412.   int i, LastRoute;
  1413.   normId(netBuf.netId, TarId);
  1414.   if (!DirectRoute(&netBuf))
  1415.   DoReRoute(target);
  1416.   /* first check for truly routed mail */
  1417.   for (i = 0; ; i++)
  1418.     {
  1419.     sprintf(temp, "R%d.%d", thisNet, i);
  1420.     makeSysName(fn, temp, &cfg.netArea);
  1421.     if (IdRouteFile(fn, Id, Name))
  1422.       {
  1423.       if (strCmpU(TarId, Id) != SAMESTRING)
  1424.       return FALSE;
  1425.  
  1426.       }
  1427.     else break;
  1428.  
  1429.     }
  1430.   /* None?  Good.  Transfer to target, which is netTemp. */
  1431.   LastRoute = FindRouteName(target, fn2);
  1432.   for (i = 0; ; i++)
  1433.     {
  1434.     sprintf(temp, "R%d.%d", thisNet, i);
  1435.     makeSysName(fn, temp, &cfg.netArea);
  1436.     if (access(fn, 0) != 0) break;
  1437.     sprintf(temp, "R%d.%d", target, LastRoute++);
  1438.     makeSysName(fn2, temp, &cfg.netArea);
  1439.     rename(fn, fn2);
  1440.  
  1441.     }
  1442.   netBuf.nbflags.HasRouted = FALSE;
  1443.   netBuf.nbHiRouteInd = 0;
  1444.   if (LastRoute != 0) netTemp.nbflags.HasRouted = TRUE;
  1445.   netTemp.nbHiRouteInd = LastRoute - 1;
  1446.   return TRUE;
  1447.  
  1448.   }
  1449. /*
  1450. * DoReRoute()
  1451. *
  1452. * This retrieve routed mail for this node from the router and pass to the new
  1453. * router, in netTemp.
  1454. */
  1455. void DoReRoute(target)
  1456. int target;
  1457.   {
  1458.   int        rover = 0, i, LastRoute;
  1459.   label    temp1, temp, Id, Name, netId, temp2;
  1460.   SYS_FILE    fn, fn2;
  1461.   char    finished = FALSE;
  1462.   LastRoute = FindRouteName(target, fn);
  1463.   getNet(netBuf.nbRoute, &nBuf1);
  1464.   normId(netBuf.netId, netId);
  1465.   do
  1466.     {
  1467.     sPrintf(temp, "R%d.%d", netBuf.nbRoute, rover);
  1468.     makeSysName(fn, temp, &cfg.netArea);
  1469.     if (!IdRouteFile(fn, Id, Name))
  1470.     finished = TRUE;
  1471.     else
  1472.       {
  1473.       if (strCmpU(Id, netId) == SAMESTRING)
  1474.         {
  1475.         sPrintf(temp, "R%d.%d", target, LastRoute++);
  1476.         makeSysName(fn2, temp, &cfg.netArea);
  1477.         rename(fn, fn2);
  1478.         CoverRouteHole(netBuf.nbRoute, rover);
  1479.  
  1480.         }
  1481.       else rover++;
  1482.  
  1483.       }
  1484.  
  1485.     }
  1486.   while (!finished);
  1487.   if (rover == 0) nBuf1.nbflags.HasRouted = FALSE;
  1488.   nBuf1.nbHiRouteInd = rover;
  1489.   putNet(netBuf.nbRoute, &nBuf1);
  1490.   if (LastRoute != 0) netTemp.nbflags.HasRouted = TRUE;
  1491.   netTemp.nbHiRouteInd = LastRoute - 1;
  1492.  
  1493.   }
  1494. /*
  1495. * ChangeRouting()
  1496. *
  1497. * This function is called when the route to a node is changing, so reroute
  1498. * mail.
  1499. */
  1500. char ChangeRouting(target)
  1501. int target;
  1502.   {
  1503.   SYS_FILE fn, newfn;
  1504.   label    temp, Id, Name;
  1505.   int    rover = 0, LastRoute;
  1506.   /* Loop through all of the mail queued for this system. */
  1507.   do
  1508.     {
  1509.     /* setup name */
  1510.     sPrintf(temp, "R%d.%d", thisNet, rover++);
  1511.     makeSysName(fn, temp, &cfg.netArea);
  1512.     if (IdRouteFile(fn, Id, Name))
  1513.       {
  1514.       if (strCmpU(OurId, Id) == SAMESTRING)
  1515.       ;    /* do nothing - sloppy programming, but is explicit */
  1516.       else if (searchNet(Id, &nBuf1) == ERROR)
  1517.         {
  1518.         printf(SURPRISE_ROUTE, Name, Id);
  1519.         if (DiscardMail)
  1520.           {
  1521.           printf(DISCARD_UNKNOWN);
  1522.           unlink(fn);
  1523.  
  1524.           }
  1525.         else return FALSE;    /* abort */
  1526.  
  1527.         }
  1528.       else return FALSE;
  1529.  
  1530.       }
  1531.     else break;    /* no more files found */
  1532.  
  1533.     }
  1534.   while (TRUE);
  1535.   /*
  1536.   * if we make it here, we just need to move the mail to the new
  1537.   * router
  1538.   */
  1539.   LastRoute = FindRouteName(target, fn);
  1540.   getNet(target, &nBuf1);
  1541.   rover = 0;
  1542.   do
  1543.     {
  1544.     /* setup name */
  1545.     sPrintf(temp, "R%d.%d", thisNet, rover++);
  1546.     makeSysName(fn, temp, &cfg.netArea);
  1547.     if (access(fn, 0) != 0) break;
  1548.     sPrintf(temp, "R%d.%d", target, LastRoute++);
  1549.     makeSysName(newfn, temp, &cfg.netArea);
  1550.     rename(fn, newfn);
  1551.  
  1552.     }
  1553.   while (TRUE);
  1554.   if (LastRoute != 0) nBuf1.nbflags.HasRouted = TRUE;
  1555.   nBuf1.nbHiRouteInd = LastRoute - 1;
  1556.   putNet(target, &nBuf1);
  1557.   netBuf.nbflags.HasRouted = FALSE;
  1558.   netBuf.nbHiRouteInd = 0;
  1559.   return TRUE;
  1560.  
  1561.   }
  1562. /*
  1563. * FindRouteName()
  1564. *
  1565. * This function finds the next route filename in sequence.
  1566. */
  1567. int FindRouteName(slot, newfn)
  1568. int slot;
  1569. SYS_FILE newfn;
  1570.   {
  1571.   int rover = 0;
  1572.   label temp;
  1573.   /* Find next unused route name */
  1574.   do
  1575.     {
  1576.     sPrintf(temp, "R%d.%d", slot, rover++);
  1577.     makeSysName(newfn, temp, &cfg.netArea);
  1578.  
  1579.     }
  1580.   while (access(newfn, 0) != -1);
  1581.   return rover - 1;
  1582.  
  1583.   }
  1584. /*
  1585. * RouteLocalMail()
  1586. *
  1587. * This function takes direct mail to a node and makes it route mail. The
  1588. * kludginess of this mess makes me wonder if direct mail should be
  1589. * automatically generated into a file, rather than just using pointers as we
  1590. * do currently.  But then what would happen for small systems?  Ah, the fun
  1591. * of system constraints.
  1592. */
  1593. void RouteLocalMail(target)
  1594. int target;
  1595.   {
  1596.   FILE *fd;
  1597.   label temp;
  1598.   SYS_FILE fn, rn;
  1599.   int rover;
  1600.   extern void (*NetPrintTarget)(), ToFile(char *fmt, ...);
  1601.   extern int (*ToFileWork)(int c);
  1602.   struct netMLstruct ml;
  1603.   if (!netBuf.nbflags.normal_mail) return;
  1604.   callSlot = thisNet;
  1605.   NetPrintTarget = ToFile;
  1606.   sPrintf(temp, "%d.ml", thisNet);
  1607.   makeSysName(fn, temp, &cfg.netArea);
  1608.   if ((fd = safeopen(fn, READ_ANY)) == NULL)
  1609.     {
  1610.     printf(ERROR_LOCAL_MAIL, netBuf.netName);
  1611.     netBuf.nbflags.normal_mail = FALSE;
  1612.     return ;
  1613.  
  1614.     }
  1615.   rover = FindRouteName(target, rn);
  1616.   sPrintf(temp, "R%d.%d", target, rover);
  1617.   makeSysName(rn, temp, &cfg.netArea);
  1618.   if ((wfd = safeopen(rn, WRITE_ANY)) == NULL)
  1619.     {
  1620.     printf("BAD ERROR: Couldn't open routing file '%s'!\n", rn);
  1621.     return;
  1622.  
  1623.     }
  1624.   ToFileWork = putRouteChar;
  1625.   ToFile("%-20s", netBuf.netId);
  1626.   ToFile("%-20s", netBuf.netName);
  1627.   ToFileWork = Encode;
  1628.   while (getMLNet(fd, ml))
  1629.     {
  1630.     if (findMessage(ml.ML_loc, ml.ML_id, TRUE))
  1631.       {
  1632.       StartEncode(putRouteChar);
  1633.       prNetStyle(0, Encode, FALSE, "");
  1634.       StopEncode();
  1635.  
  1636.       }
  1637.  
  1638.     }
  1639.   ToFileWork = putRouteChar;
  1640.   fclose(wfd);
  1641.   fclose(fd);
  1642.   unlink(fn);
  1643.   netBuf.nbflags.normal_mail = FALSE;
  1644.  
  1645.   }
  1646. /*
  1647. * putRouteChar()
  1648. *
  1649. * This function puts a character to a file.
  1650. */
  1651. int putRouteChar(c)
  1652. int c;
  1653.   {
  1654.   putc(c, wfd);
  1655.   return TRUE;
  1656.  
  1657.   }
  1658. /*
  1659. * DirectRoute()
  1660. *
  1661. * This function determines if the given node is a direct or indirect route
  1662. * for us.
  1663. */
  1664. char DirectRoute(n)
  1665. NetBuffer *n;
  1666.   {
  1667.   if (n->nbRoute == -1) return TRUE;
  1668.   if (n->nbRoute >= cfg.netSize) return TRUE;
  1669.   if (!netTab[n->nbRoute].ntflags.in_use) return FALSE;
  1670.   return (n->nbRouteGen != netTab[n->nbRoute].ntGen);
  1671.  
  1672.   }
  1673. /*
  1674. * getNetChar()
  1675. *
  1676. * This function gets a net file byte for us.
  1677. */
  1678. int getNetChar()
  1679.   {
  1680.   int c;
  1681.   if ((c = getc(upfd)) == EOF) return -1;
  1682.   return c;
  1683.  
  1684.   }
  1685. /*
  1686. * SepNameSystem()
  1687. *
  1688. * This function handles a Who Else string for us.
  1689. */
  1690. char SepNameSystem(string, person, system, buf)
  1691. NetBuffer *buf;
  1692. char *string, *person, *system;
  1693.   {
  1694.   char *c;
  1695.   int  n;
  1696.   char work[NAMESIZE * 3];    /* should be sufficient */
  1697.   strCpy(work, string);
  1698.   if ((c = strchr(work, '@')) == NULL)
  1699.   return NOT_SYSTEM;
  1700.   /* find leading spaces of "name @ system" format */
  1701.   for (n = 1; c[n] == ' ' && c[n]; n++)
  1702.   ;
  1703.   if (strLen(c + n) >= NAMESIZE)
  1704.   return BAD_FORMAT;
  1705.   strCpy(system, c + n);
  1706.   if (searchNameNet(c + n, buf) == ERROR)  /* bad - set signal of it */
  1707.   return NO_SYSTEM;
  1708.   *c = 0;
  1709.   CleanEnd(work);    /* kill trailing spaces */
  1710.   if (strLen(work) >= NAMESIZE)
  1711.   return BAD_FORMAT;
  1712.   strCpy(person, work);
  1713.   return IS_SYSTEM;
  1714.  
  1715.   }
  1716. #ifdef NEEDED
  1717. /************************************************************************/
  1718. /* CleanEnd() cleans up a message trailer for later display via    */
  1719. /*            Continue or .EH.  Inspired by Glen Heinz (MacCitadel)*/
  1720. /************************************************************************/
  1721. char *CleanEnd(text)
  1722. char *text;
  1723.   {
  1724.   char *ptr;
  1725.   int  wc, lc;
  1726.   if (strLen(text) == 0) return text;
  1727.   ptr = lbyte(text) - 1;      /* End of text of msg */
  1728.   /* Strip trailing whitespace */
  1729.   while ((*ptr == ' ' || *ptr == NEWLINE) && ptr != text)
  1730.   ptr--;
  1731.   ptr++;
  1732.   *ptr = 0;           /* tie it off with a NULL */
  1733.   /* Now we want to find a "preferred place" */
  1734.   for (wc = lc = 0, ptr--; wc < 4 && ptr != text && lc < 35; ptr--, lc++)
  1735.     {
  1736.     if (*ptr == ' ') wc++;
  1737.     if (*ptr == NEWLINE) break;     /* can't go beyond embedded NEWLINE */
  1738.  
  1739.     }
  1740.   if (ptr == text) return ptr;
  1741.   /* else */       return (ptr + 1);
  1742.  
  1743.   }
  1744. /************************************************************************/
  1745. /* lbyte() finds 0 byte of a string, returns pointer to it...      */
  1746. /************************************************************************/
  1747. char *lbyte(l)
  1748. char *l;
  1749.   {
  1750.   while (*l) l++;
  1751.   return l;
  1752.  
  1753.   }
  1754. #endif
  1755. /*
  1756. * PrintRouteIds()
  1757. *
  1758. * Prints something for us.
  1759. */
  1760. void PrintRouteIds()
  1761.   {
  1762.   label temp, Name, Id;
  1763.   SYS_FILE fn;
  1764.   int i = 0;
  1765.   do
  1766.     {
  1767.     sprintf(temp, "R%d.%d", thisNet, i++);
  1768.     makeSysName(fn, temp, &cfg.netArea);
  1769.     if (!IdRouteFile(fn, Id, Name)) break;
  1770.     printf("%s (%s)\n", Name, Id);
  1771.  
  1772.     }
  1773.   while (TRUE);
  1774.  
  1775.   }
  1776. /*
  1777. * IdRouteFile()
  1778. *
  1779. * This tries to get the routing information for a piece of mail.
  1780. */
  1781. int IdRouteFile(fn, Id, Name)
  1782. SYS_FILE fn;
  1783. label Id, Name;
  1784.   {
  1785.   label temp;
  1786.   if ((upfd = fopen(fn, READ_ANY)) == NULL) return FALSE;
  1787.   getMsgStr(getNetChar, temp, NAMESIZE);
  1788.   getMsgStr(getNetChar, Name, NAMESIZE);
  1789.   normId(temp, Id);
  1790.   NormStr(Name);
  1791.   fclose(upfd);
  1792.   return TRUE;
  1793.  
  1794.   }
  1795. /*
  1796. * CheckArea()
  1797. *
  1798. * This function checks to see if the area codes of two systems match.
  1799. */
  1800. void *CheckArea(Hop *d, char *code)
  1801.   {
  1802.   return (strCmp(code, d->Area) == 0) ? d : NULL;
  1803.  
  1804.   }
  1805. /*
  1806. * AddNewHop()
  1807. *
  1808. * Dunno.
  1809. */
  1810. void AddNewHop(char *Id)
  1811.   {
  1812.   Hop *ThisCode;
  1813.   HopNode *Node;
  1814.   char *ac;
  1815.   ac = GetDynamic(4);
  1816.   AreaCode(Id, ac);
  1817.   if ((ThisCode = SearchList(&AreaList, ac)) == NULL)
  1818.     {
  1819.     ThisCode = GetDynamic(sizeof *ThisCode);
  1820.     ThisCode->Area = ac;
  1821.     InitListValues(&ThisCode->Systems, HopSearch, NULL, NULL, NULL);
  1822.     AddData(&AreaList, ThisCode, NULL, FALSE);
  1823.  
  1824.     }
  1825.   else
  1826.     {
  1827.     free(ac);
  1828.     if ((Node = SearchList(&ThisCode->Systems, Id)) != NULL)
  1829.     return;
  1830.  
  1831.     }
  1832.   Node = GetDynamic(sizeof *Node);
  1833.   Node->Id = strdup(Id);
  1834.   Node->hopcount = 10000;
  1835.   AddData(&ThisCode->Systems, Node, NULL, FALSE);
  1836.  
  1837.   }
  1838. /*
  1839. * AreaCode()
  1840. *
  1841. * This function extracts the area code from the node ID.
  1842. */
  1843. void AreaCode(char *Id, char *Target)
  1844.   {
  1845.   int i, j;
  1846.   for (i = j = 0; j < 3 && Id[i]; i++)
  1847.   if (isdigit(Id[i]))
  1848.   Target[j++] = Id[i];
  1849.   Target[j] = 0;
  1850.  
  1851.   }
  1852. /*
  1853. * SetHopCount()
  1854. *
  1855. * This function sets a hop count on a node.
  1856. */
  1857. void SetHopCount(char *Id, int hopcount, char *RouteId)
  1858.   {
  1859.   HopNode *Node;
  1860.   if ((Node = GetHopNode(Id)) == NULL)
  1861.     {
  1862.     printf("Failure in SetHopCount!: %s", Id);
  1863.     exit(1);
  1864.  
  1865.     }
  1866.   Node->hopcount = hopcount;
  1867.   Node->RouteId = RouteId;
  1868.  
  1869.   }
  1870. /*
  1871. * GetHopNode()
  1872. *
  1873. * This function searches for the specified hop node.
  1874. */
  1875. HopNode *GetHopNode(char *Id)
  1876.   {
  1877.   char ac[5];
  1878.   Hop *ThisCode;
  1879.   HopNode *Node;
  1880.   AreaCode(Id, ac);
  1881.   if ((ThisCode = SearchList(&AreaList, ac)) == NULL)
  1882.     {
  1883.     printf("Failed at area search (%s)\n", ac);
  1884.     return NULL;
  1885.  
  1886.     }
  1887.   else
  1888.   return SearchList(&ThisCode->Systems, Id);
  1889.  
  1890.   }
  1891. /*
  1892. * IsLowerHopCount()
  1893. *
  1894. * This function tries to discover if the hop count for the specified node is
  1895. * lower than the specified hop count.
  1896. */
  1897. char IsLowerHopCount(char *Id, int HopCount)
  1898.   {
  1899.   HopNode *Node;
  1900.   if ((Node = GetHopNode(Id)) == NULL)
  1901.     {
  1902.     printf("Failure in IsLowerHopCount: %s", Id);
  1903.     exit(1);
  1904.  
  1905.     }
  1906.   return HopCount < Node->hopcount;
  1907.  
  1908.   }
  1909. /*
  1910. * FindHopCount()
  1911. *
  1912. * This function tries to find the specified hop count.
  1913. */
  1914. int FindHopCount(char *Id)
  1915.   {
  1916.   HopNode *Node;
  1917.   if ((Node = GetHopNode(Id)) == NULL)
  1918.     {
  1919.     printf("Failure in IsLowerHopCount: %s", Id);
  1920.     exit(1);
  1921.  
  1922.     }
  1923.   return Node->hopcount;
  1924.  
  1925.   }
  1926. /*
  1927. * HopSearch()
  1928. *
  1929. * This compares a hop node and an identifier.
  1930. */
  1931. void *HopSearch(HopNode *d, char *id)
  1932.   {
  1933.   if (strcmp(id, d->Id) == 0) return d;
  1934.   return NULL;
  1935.  
  1936.   }
  1937. /*
  1938. * FindDomainH()
  1939. *
  1940. * This function will help find the named domain handler.
  1941. */
  1942. static void *FindDomainH(DomainHandler *data, char *name)
  1943.   {
  1944.   return (strCmpU(data->domain, name) == SAMESTRING) ? data : NULL;
  1945.  
  1946.   }
  1947. /*
  1948. * EatDomainH()
  1949. *
  1950. * This function will eat a line from ctdldmhd.sys.
  1951. */
  1952. static void *EatDomainH(char *line)
  1953.   {
  1954.   DomainHandler *data;
  1955.   char *c, *d;
  1956.   label temp;
  1957.   if ((c = strchr(line, '#')) != NULL) *c = 0;    /* kill '#' */
  1958.   if (strlen(line) <= 3) return NULL;
  1959.   if ((c = strchr(line, ' ')) == NULL)
  1960.     {
  1961.     printf("WARNING: badly formed ctdldmhd.sys.\n");
  1962.     return NULL;
  1963.  
  1964.     }
  1965.   *c++ = 0;
  1966.   if ((d = strchr(c, ':')) == NULL)
  1967.     {
  1968.     printf("WARNING: badly formed ctdldmhd.sys.\n");
  1969.     return NULL;
  1970.  
  1971.     }
  1972.   *d++ = 0;
  1973.   NormStr(c);
  1974.   data = GetDynamic(sizeof *data);
  1975.   data->domain = strdup(line);
  1976.   data->name = strdup(c);
  1977.   normId(d, temp);
  1978.   data->nodeId = strdup(temp);
  1979.   return data;
  1980.  
  1981.   }
  1982. /*
  1983. * HandleDomains()
  1984. *
  1985. * This function is charged with making sure we    know how to get to each of the
  1986. * domain handlers we know about.
  1987. */
  1988. void HandleDomains()
  1989.   {
  1990.   void SetHandlers();
  1991.   RunList(&DomainHandlers, SetHandlers);
  1992.  
  1993.   }
  1994. /*
  1995. * SetHandlers()
  1996. *
  1997. * This function will set up the given handler if we don't know about it yet.
  1998. */
  1999. void SetHandlers(DomainHandler *data)
  2000.   {
  2001.   HopNode *Node;
  2002.   HUB   *Hub;
  2003.   PEONS *Peon;
  2004.   int   slot;
  2005.   /* is this us?  Then forget it */
  2006.   if (strCmpU(data->nodeId, OurId) == SAMESTRING) return;
  2007.   /*
  2008.   * first, see if this domain handler is on our list.  If not, then
  2009.   * add him in.
  2010.   */
  2011.   if (searchNet(data->nodeId, &netBuf) == ERROR)
  2012.     {
  2013.     if (FindHub(Systems, data->nodeId) == NULL &&
  2014.     FindGlobalPeon(Systems, data->nodeId) == NULL)
  2015.       {
  2016.       printf("WARNING: Domain Handler %s _ %s is not on this routmail map!\n", data->name, data->domain);
  2017.       return;
  2018.  
  2019.       }
  2020.     /* looks cool, so add him in. */
  2021.     AddNewNode(data->name, data->nodeId, 1);
  2022.  
  2023.     }
  2024.   /* next check if we already have a route to him.  If so, then return */
  2025.   if (netBuf.nbflags.RouteLock) return;
  2026.   /*
  2027.   * next, see if our immediate path to him (that is, the node we connect
  2028.   * directly to) is on the net.  If we happen to connect directly to him,
  2029.   * the route id will be NULL.  We store the Route Id in the system's Hop
  2030.   * count record.
  2031.   */
  2032.   if ((Node = GetHopNode(data->nodeId)) == NULL)
  2033.     {
  2034.     printf("Failure in SetHandlers: %s", data->name);
  2035.     return ;
  2036.  
  2037.     }
  2038.   if (Node->RouteId != NULL)
  2039.     {
  2040.     if ((CurHubNet = searchNet(Node->RouteId, &netBuf)) == ERROR)
  2041.       {
  2042.       if ((Hub = FindHub(Systems, Node->RouteId)) == NULL &&
  2043.       (Peon = FindGlobalPeon(Systems, Node->RouteId)) == NULL)
  2044.         {
  2045.         printf("BUG: Our path node, %s, to Domain Handler %s _ %s is not on this routmail map!", Node->RouteId, data->name, data->domain);
  2046.         return;
  2047.  
  2048.         }
  2049.       /* looks cool, so add him in. */
  2050.       if (Hub != NULL)
  2051.       AddNewNode(Hub->Name, Hub->Id, 1);
  2052.       else
  2053.       AddNewNode(Peon->Name, Peon->Id, 1);
  2054.       CurHubNet = thisNet;
  2055.  
  2056.       }
  2057.     searchNet(Node->RouteId, &netTemp);
  2058.     SetNode(data->name, data->nodeId, 1, Node->RouteId, 0, FALSE);
  2059.  
  2060.     }
  2061.  
  2062.   }
  2063. /* stub */
  2064. void splitF(FILE *log, char *fmt, ...)
  2065.   {
  2066.  
  2067.   }
  2068. #define WeServe(x)    SearchList(&Serves, x)
  2069. /*
  2070. * LocalName()
  2071. *
  2072. * This function takes a string of form <system> _ <domain> and attempts to
  2073. * discover if this domain mapped system is actually a local.  This is used
  2074. * when we're sending mail and are trying to find out if a Who Else override
  2075. * needs to be generated.  Ugly     * kludge, but, hey, that's what programming's
  2076. * all about, eh?
  2077. */
  2078. char *LocalName(char *system)
  2079.   {
  2080.   char *domain, *System;
  2081.   if ((domain = strchr(system, '_')) == NULL) return system;
  2082.   domain += 2;    /* always preceded by a space -- or so we assume */
  2083.   if (strCmpU(domain, cfg.codeBuf + cfg.nodeDomain) == SAMESTRING ||
  2084.   WeServe(domain) != NULL)
  2085.     {
  2086.     System = strdup(system);
  2087.     if ((domain = strchr(System, ' ')) == NULL)
  2088.     return system;    /* should never happen, though */
  2089.     *domain = NULL;
  2090.     if (searchNameNet(System, &netTemp) != ERROR)
  2091.       {
  2092.       free(System);
  2093.       return netTemp.netName;
  2094.  
  2095.       }
  2096.     free(System);
  2097.  
  2098.     }
  2099.   return system;
  2100.  
  2101.   }
  2102.